package com.eatme.web.sys.quartz.service.impl;

import com.eatme.web.app.coupon.common.exception.AppException;
import com.eatme.web.sys.quartz.config.QuartzConfig;
import com.eatme.web.sys.quartz.req.QuartzJobReq;
import com.eatme.web.sys.quartz.req.QuartzJobResp;
import com.eatme.web.sys.quartz.service.ISchedulerJobService;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @Description: 定时任务在线管理
 * @Author: nzc
 */
@Service
public class SchedulerJobServiceImpl implements ISchedulerJobService {

	private static final Logger LOG = LoggerFactory.getLogger(SchedulerJobServiceImpl.class);

	@Autowired
	@Lazy
	private Scheduler scheduler;


	/**
	 * 保存&启动定时任务
	 */
	@Override
	public boolean addAndschedulerJob(QuartzJobReq QuartzJobReq) {
		this.addAndschedulerJob(QuartzJobReq.getJobClassName().trim(), QuartzJobReq.getGroup(), QuartzJobReq.getCronExpression().trim());
		return true;
	}

	/**
	 * 恢复定时任务
	 */
	@Override
	public boolean resumeJob(QuartzJobReq QuartzJobReq)  {
		try {
			scheduler.resumeJob(JobKey.jobKey(QuartzJobReq.getJobClassName().trim(),QuartzJobReq.getGroup()));
		} catch (SchedulerException e) {
			LOG.error("重启定时任务失败: {}",e);
			throw new AppException("重启定时任务失败,调度异常",e);
		}
		return true;
	}

	@Override
	public void test(String param) {
		System.out.println("param====>"+param);
	}







	@Override
	public void resetJob(QuartzJobReq job) {
		try {
			TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobClassName(), job.getGroup());
			// 表达式创建器
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
			CronTriggerImpl cronTrigger= (CronTriggerImpl) scheduler.getTrigger(triggerKey);
			cronTrigger.setStartTime(new Date()); //
			CronTrigger trigger = cronTrigger;
			// 按新的cronExpression表达式重新构建trigger
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withDescription(job.getDescription()).withSchedule(scheduleBuilder).build();
			// 按新的trigger重新设置job执行
			scheduler.rescheduleJob(triggerKey,trigger);
		} catch (SchedulerException e) {
			LOG.error("更新定时任务失败: {}",e);
			throw new AppException("更新定时任务失败: 调度异常",e);
		}
	}

	@Override
	public void deleteJob(QuartzJobReq QuartzJobReq) {
		// Scheduler scheduler1 = schedulerFactoryBean.get
		try {
			scheduler.pauseTrigger(TriggerKey.triggerKey(QuartzJobReq.getJobClassName(),QuartzJobReq.getGroup()));
			scheduler.unscheduleJob(TriggerKey.triggerKey(QuartzJobReq.getJobClassName(),QuartzJobReq.getGroup()));
			scheduler.deleteJob(JobKey.jobKey(QuartzJobReq.getJobClassName(),QuartzJobReq.getGroup()));
		} catch (SchedulerException e) {
			LOG.error("删除定时任务失败:调度异常");
			throw new AppException("删除定时任务失败:调度异常",e);
		}
		LOG.info("删除定时任务结束");

	}

	@Override
	public List<QuartzJobResp> queryJob() {

		List<QuartzJobResp> list = new ArrayList<>();
		try {
			for (String groupName : scheduler.getJobGroupNames()) {
				for (JobKey jobKey: scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))){
					QuartzJobResp resp = new QuartzJobResp();
					resp.setJobClassName(jobKey.getName());
					resp.setGroup(jobKey.getGroup());

					// get job`s triger
					List<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);
					CronTrigger cronTrigger = (CronTrigger) triggers.get(0);
					resp.setNextFireTime(cronTrigger.getNextFireTime());
					resp.setPreviousFireTime(cronTrigger.getPreviousFireTime());
					resp.setCronExpression(cronTrigger.getCronExpression());
					resp.setDescription(cronTrigger.getDescription());
					Trigger.TriggerState triggerState = scheduler.getTriggerState(cronTrigger.getKey());
					resp.setState(triggerState.name());
					list.add(resp);
				}
			}
		} catch (SchedulerException e) {
			LOG.error("查看定时任务失败: {}",e);
			throw new AppException("查看定时任务失败",e);
		}
		LOG.info("查看定时任务结果: {}",list);
		return list;
	}

	@Override
	public void triggerJob(String jobClassName, String jobGroupName) {
		try {
			scheduler.triggerJob(JobKey.jobKey(jobClassName, jobGroupName));
		} catch (SchedulerException e) {
			LOG.error("手动触发定时任务失败:",e);
			throw new AppException("手动触发job失败:调度异常",e);
		}
	}

	@Override
	public void pauseJob(String iobClassName, String group) {
		try {
			scheduler.pauseJob(JobKey.jobKey(iobClassName,group));
		} catch (SchedulerException e) {
			LOG.error("暂停定时任务失败:",e);
			throw new AppException("暂停job失败:调度异常",e);
		}
	}

	/**
	 * 添加定时任务
	 * 
	 * @param jobClassName
	 * @param cronExpression
	 */
	private void addAndschedulerJob(String jobClassName,String jobGroupName, String cronExpression) {
		try {
			// 启动调度器
			scheduler.start();
			Random random = new Random();
			int count = random.nextInt(10);
			// 构建job信息
			JobDetail jobDetail = JobBuilder.
					newJob((Class<? extends Job>) Class.forName(jobClassName)).
					withIdentity(jobClassName,jobGroupName)
					// job传递参数 示例
					//.usingJobData("","")

					// 更新jobDataMap 示例
					//.usingJobData("count",count)
					.build();
			//JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(jobClassName).usingJobData("parameter", parameter).build();

			// 表达式调度构建器(即任务执行的时间)
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

			// 通过DateBuilder 创建时间
			//Date date = DateBuilder.futureDate(15,DateBuilder.IntervalUnit.SECOND);
			// 按新的cronExpression表达式构建一个新的trigger
			CronTrigger trigger = TriggerBuilder.newTrigger()
					// .startAt()
					// .endAt()
					// .withPriority() //优先级
					.withIdentity(jobClassName,"default")
					// .usingJobData()
					.withSchedule(scheduleBuilder).build();



			scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			LOG.info("创建定时任务失败,调度异常: {}",e);
			throw new AppException("创建定时任务失败: {}", e);
		} catch (ClassNotFoundException e) {
			LOG.info("创建定时任务失败,任务类不存在: {}",e);
			throw new AppException(e.getMessage(), e);
		}
	}

	/**
	 * 删除定时任务
	 * 
	 * @param jobClassName
	 */
	private void schedulerDelete(String jobClassName) throws AppException {
		try {
			/*使用给定的键暂停Trigger 。*/
			scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
			/*从调度程序中删除指示的Trigger */
			scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
			/*从 Scheduler 中删除已识别的Job - 以及任何关联的Trigger */
			scheduler.deleteJob(JobKey.jobKey(jobClassName));
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			throw new AppException("删除定时任务失败");
		}
	}

	private static Job getClass(String classname) throws Exception {
		Class<?> class1 = Class.forName(classname);
		return (Job) class1.newInstance();
	}




}
